package xin.shaozeming.base.common.aop;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import xin.shaozeming.base.common.Enum.base.LoggerType;
import xin.shaozeming.base.common.ex.CustomerException;
import xin.shaozeming.base.common.servlet.ParameterRequestWrapper;
import xin.shaozeming.base.common.utils.WordUtils;
import xin.shaozeming.base.po.SysLogPO;
import xin.shaozeming.base.service.SysLogService;
import xin.shaozeming.base.service.UserService;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * @author: 邵泽铭
 * @date: 2019/4/17
 * @description:
 **/


@Log4j2
@Component
@Aspect
@Order(10)
public class SysLogger {

    @Resource
    private SysLogService sysLogService;

    @Pointcut("@annotation(xin.shaozeming.base.common.aop.annotation.SysLogger)")
    private void cutPoint() {
    }

    ;

    @AfterReturning("cutPoint()")
    private void process(JoinPoint joinPoint) {

        Object[] args = joinPoint.getArgs();
        xin.shaozeming.base.common.aop.annotation.SysLogger methodLogger = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(xin.shaozeming.base.common.aop.annotation.SysLogger.class);

        xin.shaozeming.base.common.aop.annotation.SysLogger classLogger = joinPoint.getTarget().getClass().getAnnotation(xin.shaozeming.base.common.aop.annotation.SysLogger.class);


        if (methodLogger == null || classLogger == null) {
            return;
        }




        /*获取日志内容*/
        String content = classLogger.group() + methodLogger.name();

        /*获取日志类型*/
        LoggerType type = methodLogger.type();

        /*获取request参数*/
        ParameterRequestWrapper requestWrapper = (ParameterRequestWrapper) ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

        for (Object arg : args) {
            if (arg instanceof ParameterRequestWrapper) {
                requestWrapper = (ParameterRequestWrapper) arg;
            }
        }


        /*save 保存更新同一个方法，需要区分,根据request中参数区分*/
        if (type.equals(LoggerType.SAVE)) {
            String id = methodLogger.id();
            String idRs = requestWrapper.getParameter(id);
            if (StringUtils.isEmpty(idRs)) {
                type = LoggerType.ADD;
                content = classLogger.group() + "新增";
            } else {
                type = LoggerType.UPDATE;
                content = classLogger.group() + "修改";
            }
        }
        /*log优先*/
        if (!StringUtils.isEmpty(methodLogger.log())) {
            content = methodLogger.log();
        }

        SysLogPO sysLogPO = new SysLogPO();
        sysLogPO.setContent(content);
        sysLogPO.setType(type);
        sysLogPO.setCreatedTime(new Date());
        sysLogPO.setModifiedTime(new Date());




        /*获取用户*/
        String username = requestWrapper.getParameter("x_username");
        /*登录注册一些特殊情况需要从参数中获取username*/
        if (methodLogger.user()) {
            username = args[methodLogger.userPosition() - 1] == null ? "" : args[methodLogger.userPosition() - 1].toString();
        }

        sysLogPO.setUsername(username);

        /*获取参数*/
        Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
        parameterMap.remove("x_username");

        Map<String, String> paramMap = new HashMap<>();

        for (Map.Entry<String, String[]> kv : parameterMap.entrySet()) {
            paramMap.put(kv.getKey(), kv.getValue()[0]);
        }
        String params = JSONObject.toJSONString(paramMap);
        sysLogPO.setParams(params);

        /*获取ip*/

        String id = "";
        String ip = requestWrapper.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = requestWrapper.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = requestWrapper.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = requestWrapper.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = requestWrapper.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = requestWrapper.getRemoteAddr();
        }

        sysLogPO.setIp(ip);
        try {
            sysLogService.save(sysLogPO);
        } catch (Exception e) {
            log.error("记录logger失败:{}", e.getMessage());
        }

    }
}
